package process

import (
	utils "chatOnline/client/uitls"
	"chatOnline/common/message"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"net"
	"os"
)

type UserProcess struct {
}

// 写一个函数，完成注册
func (this *UserProcess) Register(userId int, userPwd string, userName string) (err error) {
	// 1. 连接到服务器
	conn, err := net.Dial("tcp", "localhost:8889")
	if err != nil {
		fmt.Println("net.Dial err =", err)
		return err
	}
	// 延时关闭
	defer conn.Close()

	// 2.通过conn发送消息给服务
	var mes message.Message
	mes.Type = message.RegisterMesType
	// 3. 创建一个LoginMes 结构体
	var registerMes message.RegisterMes
	registerMes.User.UserId = userId
	registerMes.User.UserPwd = userPwd
	registerMes.User.UserName = userName

	// 4. 将loginMes 序列化
	data, err := json.Marshal(registerMes)
	if err != nil {
		fmt.Println("josn.Marshal err=", err)
		return err
	}
	//5 .data 赋值给mes.Data 字段
	mes.Data = string(data)

	// 6. mes 序列化 得到的是byte 切片
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("josn.Marshal err=", err)
		return err
	}

	// 这里需要处理服务器返回的消息
	// tf 可考虑定义成全局变量
	tf := &utils.Transfer{
		Conn: conn,
	}

	err = tf.WritePkg(data)
	if err != nil {
		fmt.Println(" 发送注册信息 writePkg(conn) err=", err)
		return
	}

	mes, err = tf.ReadPkg() // mes 就是
	if err != nil {
		fmt.Println("readPkg(conn) err=", err)
		return
	}

	// 将mes的Data部分反序列化成logicResMes
	var registerResMes message.RegisterResMes
	err = json.Unmarshal([]byte(mes.Data), &registerResMes)
	if registerResMes.Code == 200 {

		// 1. 显示我们登录成功的菜单
		fmt.Println("注册成功!")
		os.Exit(0)

	} else {
		fmt.Println(registerResMes.Error)
		os.Exit(0)
	}

	return

}

// 写一个函数，完成登录
func (this *UserProcess) Login(userId int, userPwd string) (err error) {
	// 制定协议
	//fmt.Printf("userId=%d userPwd=%s\n", userId, userPwd)
	//
	//return nil
	// 1. 连接到服务器
	conn, err := net.Dial("tcp", "localhost:8889")
	if err != nil {
		fmt.Println("net.Dial err =", err)
		return err
	}
	// 延时关闭
	defer conn.Close()

	// 2.通过conn发送消息给服务
	var mes message.Message
	mes.Type = message.LoginMesType
	// 3. 创建一个LoginMes 结构体
	var loginMes message.LoginMes
	loginMes.UserId = userId
	loginMes.UserPwd = userPwd

	// 4. 将loginMes 序列化
	data, err := json.Marshal(loginMes)
	if err != nil {
		fmt.Println("josn.Marshal err=", err)
		return err
	}
	//5 .data 赋值给mes.Data 字段
	mes.Data = string(data)

	// 6. mes 序列化 得到的是byte 切片
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("josn.Marshal err=", err)
		return err
	}

	// 7 此时 data 即为我们要发送的消息
	// 7.1 先把data 长度的发送给服务器
	// 先获取到data 的长度 ，转成一个表示长度的byte切片
	var pkgLen uint32
	pkgLen = uint32(len(data))
	var buf [4]byte
	binary.BigEndian.PutUint32(buf[0:4], pkgLen)
	// 发送长度
	n, err := conn.Write(buf[0:4])
	if n != 4 || err != nil {
		fmt.Println("conn.Write(btyes) fail =", err)
		return
	}

	fmt.Printf("客户端，发送消息长度=%d, 内容=%s\n", len(data), string(data))
	_, err = conn.Write(data)
	if err != nil {
		fmt.Println("json.Writer(data) err=", err)
		return err
	}

	// 这里需要处理服务器返回的消息
	// tf 可考虑定义成全局变量
	tf := &utils.Transfer{
		Conn: conn,
	}
	mes, err = tf.ReadPkg() // mes 就是
	if err != nil {
		fmt.Println("readPkg(conn) err=", err)
		return
	}

	// 将mes的Data部分反序列化成logicResMes
	var loginResMes message.LoginResMes
	err = json.Unmarshal([]byte(mes.Data), &loginResMes)
	if loginResMes.Code == 200 {
		// 初始化CurUser
		CurUser.Conn = conn
		CurUser.UserId = userId
		CurUser.UserStatus = message.UserOnline

		// 显示当前在线用户列表
		fmt.Println("当前在线用户id")
		for _, v := range loginResMes.UserIds {
			if v == userId {
				continue
			}
			fmt.Println("用户id:\t", v)
			// 完成客户端的onlineUsers 初始化
			user := &message.User{
				UserId:     v,
				UserStatus: message.UserOnline,
			}
			onlineUser[v] = user
		}
		fmt.Print("\n\n")
		// 启动协程
		// 该协程保持和服务器端的通讯，如果服务器端有数据推送给客户端
		// 则接收并显示在客户端的终端
		go serverProcessMes(conn)
		// 1. 显示我们登录成功的菜单
		for {
			showMenu()
		}

	} else {
		fmt.Println(loginResMes.Error)
	}

	return

}
